package com.diamond.web.aspect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.validation.Valid;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;

import com.diamond.core.entity.JSONResult;
import com.diamond.core.entity.Result;


/**
 * 用于验证 response请求里的参数
 * @author Diamond
 *
 */
@Component
@Aspect
public class ResponseBodyAspect {
	
	@Pointcut("execution(* com.diamond.web.controller..*(..))")
	public void validData(){};
	
	/**
	 * 对所有ResponseBody注解的变量进行
	 * @param pj
	 * @return
	 * @throws Throwable
	 */
	@Around("validData()&&@annotation(org.springframework.web.bind.annotation.ResponseBody)")
	public Object around(ProceedingJoinPoint pj) throws Throwable{
		MethodSignature signature  = (MethodSignature) pj.getSignature();
		Method method = signature.getMethod();
		
		for(int i=0;i<pj.getArgs().length ;i++){
			Object param = pj.getArgs()[i];
			if(param!=null){
				try{
					Long number = Long.parseLong(param.toString());  //直接将参数转换为整数类型，如果转换成功，并且参数等于-1，则将该参数设置为空
					if(number==-1){  
						pj.getArgs()[i]=null;
					}
				}catch (NumberFormatException e) {
					if(param instanceof String){  //如果参数为字符串，并且参数为空格或者空  则该参数设置为空
						if(StringUtils.isBlank(param.toString())){
							pj.getArgs()[i]=null;
						}
					}
				}
			}
		}
		if(Result.class.equals(method.getReturnType())){
			Annotation[][] anno2d = method.getParameterAnnotations();
			for(int i=0;i<anno2d.length;i++){
				if(hasValidAnnotation(anno2d[i])){
					BindingResult bindResult = (BindingResult) pj.getArgs()[i+1];
					if(bindResult!=null&&bindResult.hasErrors()){
						Result result= buildErrorJsonResult(bindResult);
						return result;
					}
				}
			}
		}
		
		return pj.proceed(pj.getArgs());
	}

	private Result buildErrorJsonResult(BindingResult bindResult) {
		List<Map<String,String>> errorList= new ArrayList<Map<String,String>>();
		JSONResult<List<Map<String,String>>> result = new JSONResult<List<Map<String,String>>>();
		List<ObjectError> objectErrorList = bindResult.getAllErrors();
		for (ObjectError objectError : objectErrorList) {
			if(objectError instanceof FieldError){
				Map<String,String> error = new HashMap<String, String>();
				FieldError fielderror = (FieldError) objectError;
				error.put(fielderror.getField(),fielderror.getDefaultMessage());
				errorList.add(error);
			}
		}
		result.setData(errorList);
		result.setSuccess(false);
		return result;
	}

	private boolean hasValidAnnotation(Annotation[] annotations) {
		for (Annotation annotation : annotations) {
			if(annotation instanceof Valid){
				return true;
			}
		}
		return false;
	}
}
